from django.contrib.auth.models import AbstractUser
from django.db import models
from MSB_ERP.utils.base_model import BaseModel


class MenuModel(BaseModel):
    '''
    功能菜单的模型类
    '''
    # null=True他是基于数据库的，意思是他可以为空
    # blank=True不单是数据库可以表示为空，提交数据（表单）的时候也可以为空
    number = models.IntegerField('排序数字', blank=True, null=True)
    url = models.CharField('菜单访问的url地址', max_length=256, blank=True, null=True)
    name = models.CharField('菜单的名字', max_length=50)
    # 不会真正把数据库中的数据删除，默认是0，如果是1的话，表示删除
    '''不会真正的吧数据库的数据删除的，默认是0，如果是1表示删除'''
    delete_flag = models.CharField('删除的标记', max_length=1, default='0')
    # 多对一的关联关系（直接关联自己，直接用self就行了）
    # related_name反向关联属性的名字
    # models.CASCADE级联删除，当把父菜单删除的时候，所有子菜单都会删除
    parent = models.ForeignKey('self', blank=True, null=True, related_name='childent', on_delete=models.CASCADE)

    class Meta:
        db_table = 't_munu'
        verbose_name = '功能菜单表'
        verbose_name_plural = verbose_name
        ordering = ['number']

    def __str__(self):
        return self.name


class UserModel(AbstractUser, BaseModel):
    '''ERP的系统模型类，默认采用django自带的user'''
    # unique=True字段是唯一的
    phone = models.CharField('手机号码', max_length=11, unique=True, blank=True, null=True)
    real_name = models.CharField('真实的姓名', max_length=64, unique=True, blank=True, null=True)

    # 用户所有的角色
    roles = models.ManyToManyField('RolesModel',db_table='t_user_roles',blank=True)

    # 用户所在的部门（在用户在跟他关联一下）
    dept = models.ForeignKey('DeptModel',blank=True,null=True,on_delete=models.SET_NULL,verbose_name='用户所在的部门')

    class Meta:
        db_table = 't_user'
        verbose_name = '系统用户表'
        verbose_name_plural = verbose_name
        ordering = ['id']


    def __str__(self):
        return self.username + ":" + self.real_name


class PermissionsModel(BaseModel):
    """
    权限模型，包含两个要素钥匙：资源，操作（新增成员，新增是操作，成员是资源）
    """
    method_choices = (
        ('POST', '增'),
        ('DELETE', '删'),
        ('PUT', '改'),
        ('PATCH', '局部修改'),
        ('GET', '查')
    )
    '''
    只要是choices参数的字段，如果你想获取key或者value的话，默认获取的是key，
    如果想或者value，就可以get_字段名_display()
    例：print(permission.methods) 获取key
        print(permission.get_methods_display()) 获取value
    '''
    name = models.CharField(max_length=50, verbose_name='权限名')
    is_menu = models.BooleanField(verbose_name='是否为菜单', default=True)  # True为菜单,False为接口
    # 操作（choices表示一种约束，他只能选上面元组中的值）
    method = models.CharField(max_length=8, blank=True, default='', choices=method_choices,
                              verbose_name='请求方法')  # 如果是父菜单的话是可以没有的
    path = models.CharField(max_length=200, blank=True, default='', verbose_name='访问URL地址')
    # 资源
    menu = models.ForeignKey('MenuModel', null=True, blank=True, related_name='permissions_list', on_delete=models.CASCADE) # 外键
    desc = models.CharField(max_length=512, blank=True, default='', verbose_name='权限描述')

    def __str__(self):
        return self.name

    class Meta:
        db_table = 't_permissions' # 表名
        verbose_name = '权限' # 表名描述
        verbose_name_plural = verbose_name
        ordering = ['id']  # 根据什么来进行排序的

class RolesModel(BaseModel):
    """
    角色模型
    """
    name = models.CharField(max_length=32, unique=True, verbose_name='角色名字')
    # 因为是多对多的缘故，所以要定义中间表db_table（表名自定义即可）
    permissions = models.ManyToManyField('PermissionsModel', db_table='t_roles_permissions',
                                         blank=True, verbose_name='权限')
    # 注意在用户模型中最好也要加ManyToManyField

    def __str__(self):
        return self.name

    class Meta:
        db_table = 't_roles'
        verbose_name = '角色'
        verbose_name_plural = verbose_name

class DeptModel(BaseModel):
    """
    用户所在部门模型
    """
    # 通过parent这个属性就可以判断这个模型类就是树形结构

    name = models.CharField('部门名称',max_length=32, unique=True)
    address = models.CharField('部门所在的地址',max_length=256,null=True,blank=True)
    # 这里的关联关系表示自己关联自己（null表示数据库中可以为空，blank表示传参的时候可以为空）,related_name反向关联的名字,
    parent = models.ForeignKey('self',null=True,blank=True,related_name='children',on_delete=models.CASCADE,verbose_name='部门所在的父部门')

    def __str__(self):
        return self.name

    class Meta:
        db_table = 't_dept'
        verbose_name = '部门'
        verbose_name_plural = verbose_name
        ordering = ['id']
